/*
 * @copyright fxsen <br/>
 * @date 2022/4/9 23:46 <br/>
 * @email <a href="mailto:fuqiang@wisesoft.org.cn">
 * @author fxsen
 */
package com.fxsen.commons.utils;

import com.alibaba.fastjson.JSONObject;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * @author fxsen
 * @date 2022/4/9 23:46
 * @email <a href="mailto:fuqiang@wisesoft.org.cn">
 */
public class HttpContextUtils {
    //这里输入你申请到的key
    private static final String APP_KEY="GJUBZ-JAYRD-ST34H-HSFQA-43VXH-7RFSK";
    private static final String NUKNOWN = "unknown";
    private static final String[] ADDR_HEADER = { "X-Forwarded-For",
            "Proxy-Client-IP", "WL-Proxy-Client-IP", "X-Real-IP" };
    /**Wap网关Via头信息中特有的描述信息*/
    private static final String[] MOBILE_GATE_WAY_HEADERS =new String[]{
            "ZXWAP",//中兴提供的wap网关的via信息，例如：Via=ZXWAP GateWayZTE Technologies，
            "chinamobile.com",//中国移动的诺基亚wap网关，例如：Via=WTP/1.1 GDSZ-PB-GW003-WAP07.gd.chinamobile.com (Nokia WAP Gateway 4.1 CD1/ECD13_D/4.1.04)
            "monternet.com",//移动梦网的网关，例如：Via=WTP/1.1 BJBJ-PS-WAP1-GW08.bj1.monternet.com. (Nokia WAP Gateway 4.1 CD1/ECD13_E/4.1.05)
            "infoX",//华为提供的wap网关，例如：Via=HTTP/1.1 GDGZ-PS-GW011-WAP2 (infoX-WISG Huawei Technologies)，或Via=infoX WAP Gateway V300R001 Huawei Technologies
            "XMS 724Solutions HTG",//国外电信运营商的wap网关，不知道是哪一家
            "wap.lizongbo.com",//自己测试时模拟的头信息
            "Bytemobile",//貌似是一个给移动互联网提供解决方案提高网络运行效率的，例如：Via=1.1 Bytemobile OSN WebProxy/5.1
    };
    /**电脑上的IE或Firefox浏览器等的User-Agent关键词*/
    private static final String[] PC_HEADERS = new String[]{
            "Windows 98",
            "Windows ME",
            "Windows 2000",
            "Windows XP",
            "Windows NT",
            "Ubuntu"
    };
    /**手机浏览器的User-Agent里的关键词*/
    private static final String[] MOBILE_USER_AGENTS =new String[]{
            "Nokia",//诺基亚，有山寨机也写这个的，总还算是手机，Mozilla/5.0 (Nokia5800 XpressMusic)UC AppleWebkit(like Gecko) Safari/530
            "SAMSUNG",//三星手机 SAMSUNG-GT-B7722/1.0+SHP/VPP/R5+Dolfin/1.5+Nextreaming+SMM-MMS/1.2.0+profile/MIDP-2.1+configuration/CLDC-1.1
            "MIDP-2",//j2me2.0，Mozilla/5.0 (SymbianOS/9.3; U; Series60/3.2 NokiaE75-1 /110.48.125 Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML like Gecko) Safari/413
            "CLDC1.1",//M600/MIDP2.0/CLDC1.1/Screen-240X320
            "SymbianOS",//塞班系统的，
            "MAUI",//MTK山寨机默认ua
            "UNTRUSTED/1.0",//疑似山寨机的ua，基本可以确定还是手机
            "Windows CE",//Windows CE，Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)
            "iPhone",//iPhone是否也转wap？不管它，先区分出来再说。Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; zh-cn) AppleWebKit/532.9 (KHTML like Gecko) Mobile/8B117
            "iPad",//iPad的ua，Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; zh-cn) AppleWebKit/531.21.10 (KHTML like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10
            "Android",//Android是否也转wap？Mozilla/5.0 (Linux; U; Android 2.1-update1; zh-cn; XT800 Build/TITA_M2_16.22.7) AppleWebKit/530.17 (KHTML like Gecko) Version/4.0 Mobile Safari/530.17
            "BlackBerry",//BlackBerry8310/2.7.0.106-4.5.0.182
            "UCWEB",//ucweb是否只给wap页面？ Nokia5800 XpressMusic/UCWEB7.5.0.66/50/999
            "ucweb",//小写的ucweb貌似是uc的代理服务器Mozilla/6.0 (compatible; MSIE 6.0;) Opera ucweb-squid
            "BREW",//很奇怪的ua，例如：REW-Applet/0x20068888 (BREW/3.1.5.20; DeviceId: 40105; Lang: zhcn) ucweb-squid
            "J2ME",//很奇怪的ua，只有J2ME四个字母
            "YULONG",//宇龙手机，YULONG-CoolpadN68/10.14 IPANEL/2.0 CTC/1.0
            "YuLong",//还是宇龙
            "COOLPAD",//宇龙酷派YL-COOLPADS100/08.10.S100 POLARIS/2.9 CTC/1.0
            "TIANYU",//天语手机TIANYU-KTOUCH/V209/MIDP2.0/CLDC1.1/Screen-240X320
            "TY-",//天语，TY-F6229/701116_6215_V0230 JUPITOR/2.2 CTC/1.0
            "K-Touch",//还是天语K-Touch_N2200_CMCC/TBG110022_1223_V0801 MTK/6223 Release/30.07.2008 Browser/WAP2.0
            "Haier",//海尔手机，Haier-HG-M217_CMCC/3.0 Release/12.1.2007 Browser/WAP2.0
            "DOPOD",//多普达手机
            "Lenovo",// 联想手机，Lenovo-P650WG/S100 LMP/LML Release/2010.02.22 Profile/MIDP2.0 Configuration/CLDC1.1
            "LENOVO",// 联想手机，比如：LENOVO-P780/176A
            "HUAQIN",//华勤手机
            "AIGO-",//爱国者居然也出过手机，AIGO-800C/2.04 TMSS-BROWSER/1.0.0 CTC/1.0
            "CTC/1.0",//含义不明
            "CTC/2.0",//含义不明
            "CMCC",//移动定制手机，K-Touch_N2200_CMCC/TBG110022_1223_V0801 MTK/6223 Release/30.07.2008 Browser/WAP2.0
            "DAXIAN",//大显手机DAXIAN X180 UP.Browser/6.2.3.2(GUI) MMP/2.0
            "MOT-",//摩托罗拉，MOT-MOTOROKRE6/1.0 LinuxOS/2.4.20 Release/8.4.2006 Browser/Opera8.00 Profile/MIDP2.0 Configuration/CLDC1.1 Software/R533_G_11.10.54R
            "SonyEricsson",// 索爱手机，SonyEricssonP990i/R100 Mozilla/4.0 (compatible; MSIE 6.0; Symbian OS; 405) Opera 8.65 [zh-CN]
            "GIONEE",//金立手机
            "HTC",//HTC手机
            "ZTE",//中兴手机，ZTE-A211/P109A2V1.0.0/WAP2.0 Profile
            "HUAWEI",//华为手机，
            "webOS",//palm手机，Mozilla/5.0 (webOS/1.4.5; U; zh-CN) AppleWebKit/532.2 (KHTML like Gecko) Version/1.0 Safari/532.2 Pre/1.0
            "GoBrowser",//3g GoBrowser.User-Agent=Nokia5230/GoBrowser/2.0.290 Safari
            "IEMobile",//Windows CE手机自带浏览器，
            "WAP2.0"//支持wap 2.0的
    };
    /**
     * 获取query参数
     * @param request
     * @return
     */
    public static Map<String, String> getParameterMapAll(HttpServletRequest request) {
        Enumeration<String> parameters = request.getParameterNames();
        Map<String, String> params = new HashMap<>();
        while (parameters.hasMoreElements()) {
            String parameter = parameters.nextElement();
            String value = request.getParameter(parameter);
            params.put(parameter, value);
        }
        return params;
    }
    /**
     * 获取请求Body
     *
     * @param request
     * @return
     */
    public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString().replace(" ","");
    }
    /**
     * description 获取客户端IP
     *
     * @param request
     * @return java.lang.String
     * @version 1.0
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 如果是多级代理，那么取第一个IP为客户端IP
        if (ip != null && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(",")).trim();
        }
        if ("127.0.0.1".equals(ip) || "localhost".equals(ip)) {
            // 获取本机真正的ip地址
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                LoggerUtils.error(e.getMessage(), e);
            }
        }
        return ip;
    }
    /**
     * 请求ip对应的地址经纬度
     * @return
     */
    public static String getIpAddr(String ip){
        RestTemplate restTemplate=new RestTemplate();
        JSONObject forObject = restTemplate.getForObject("https://apis.map.qq.com/ws/location/v1/ip?ip="+ip+"&key="+APP_KEY,
                JSONObject.class);
        if (forObject == null){
            return "局域网地址";
        }
        if (!forObject.containsKey("result") && forObject.containsKey("message")){
            return forObject.getString("message");
        }
        JSONObject result = forObject.getJSONObject("result");
        if (null == result){
            return "局域网地址";
        }
        JSONObject location = result.getJSONObject("location");
        if (location == null){
            return "局域网地址";
        }
        Object lat = location.get("lat");
        Object lng = location.get("lng");
        String latLng=lat.toString()+","+lng.toString();
        System.out.println("经纬度"+latLng);
        //获取经纬度对应的地址原来的不详细没有给到街道
        JSONObject forObject1 = restTemplate.getForObject("https://apis.map.qq.com/ws/geocoder/v1/?location=" + latLng + "&key=" + APP_KEY, JSONObject.class);
        if (forObject1 == null){
            return "局域网地址";
        }
        //位置描述
        Object o = forObject1.getJSONObject("result").get("address");
        return  o.toString();
    }
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }
    /**
     * 获取浏览器
     * @author: <a href="mailto:fxsen@foxmail.com">Fxsen</a>
     * @date: 2022/8/11 14:48
 	 * @param: request
 	 * @return: {@link String}
    **/
    public static String getBrowser(HttpServletRequest request) {
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        return browser.getName();
    }
    /**
     * 根据当前请求的特征，判断该请求是否来自手机终端，主要检测特殊的头信息，以及user-Agent这个header
     * @param request http请求
     * @return 如果命中手机特征规则，则返回对应的特征字符串
     */
    public static boolean isMobileDevice(HttpServletRequest request){
        boolean pcFlag = false;
        boolean mobileFlag = false;
        String via = request.getHeader("Via");
        String userAgent = request.getHeader("user-agent");
        for (int i = 0; via!=null && !via.trim().equals("") && i < MOBILE_GATE_WAY_HEADERS.length; i++) {
            if(via.contains(MOBILE_GATE_WAY_HEADERS[i])){
                mobileFlag = true;
                break;
            }
        }
        for (int i = 0; !mobileFlag && userAgent!=null && !userAgent.trim().equals("") && i < MOBILE_USER_AGENTS.length; i++) {
            if(userAgent.contains(MOBILE_USER_AGENTS[i])){
                mobileFlag = true;
                break;
            }
        }
        for (int i = 0; userAgent!=null && !userAgent.trim().equals("") && i < PC_HEADERS.length; i++) {
            if(userAgent.contains(PC_HEADERS[i])){
                pcFlag = true;
            }
        }
        if(mobileFlag && !pcFlag){
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(getIpAddr("124.161.16.164"));
    }
}
